<?php
/**
 * Created by PhpStorm.
 * User: ZhangYinxian
 * Date: 2016-10-10
 * Time: 10:03
 */

namespace app\index\logic;

/**
 * 杂质条件分析工具
 * Class ImpurityConditionUtil
 * @package app\index\logic
 */
class ImpurityConditionUtil
{
    public static function contain($aminoLocations, $condition){
        $is_valid = false;
        $condition1s = self::getConditions($condition);
        if (is_null($condition1s)) return false;

        foreach ($condition1s as $tmp_condition) {
            if (strpos($tmp_condition, '+') > 0) { // 两个元素需要连接出现
                $aminos = explode('+', $tmp_condition);
                $start_index = 0;
                if (count($aminos) <= 1) continue;

                $amino = trim($aminos[0]);
                $amino_locations = isset($aminoLocations[0]) ? $aminoLocations[0] : null;
                if (is_null($amino_locations)) break;
                foreach ($amino_locations as $index => $aminoLocation) {
                    if ($amino == $aminoLocation['single'] || $amino == $aminoLocation['full']) {
                        $start_index = $index;
                        break;
                    };
                }
                if ($start_index==0) continue;

                if (isset($amino_locations[$start_index + 1])) {
                    $second_amino = trim($aminos[1]);
                    $second_location = $amino_locations[$start_index + 1];
                    if ($second_amino == $second_location['single'] || $second_amino == $second_location['full']) {
                        $is_valid = true;
                    }
                }
            }else if(strpos($tmp_condition, ')[')>-1){
                $start_index = strpos($tmp_condition, ')[');

                $end_index = strpos($tmp_condition, ']');
                $tmp_value = substr($tmp_condition, $start_index+2, $end_index - $start_index - 2);
                $tmp_amino_str = substr($tmp_condition, 1, $start_index-1);
                $tmp_amino_list = explode('|', trim($tmp_amino_str));
                if (count($tmp_amino_list)==0) break;
                $tmp_count = 0;
                foreach ($tmp_amino_list as $tmp_amino){
                    foreach ($aminoLocations as $chainLocations){
                        foreach ($chainLocations as $aminoLocation){
                            if ($tmp_amino==$aminoLocation['single']){
                                $tmp_count++;
                            }
                        }
                    }

                }
                if ($tmp_count>=$tmp_value){
                    $is_valid = true;
                }
            } else {
                foreach ($aminoLocations as $chain_locations){
                    foreach ($chain_locations as $aminoLocation) {
                        if ($tmp_condition == $aminoLocation['single'] || $tmp_condition == $aminoLocation['full']) {
                            $is_valid = true;
                        }
                    }
                }

            }
        }
        return $is_valid;
    }

    public static function cyclo($amino_locations, $condition){
        $is_valid = false;

        return $is_valid;
    }

    public static function cycloEnable($aminoLocations, $condition, $dataList){
        $is_valid1 = true;
        $is_valid2 = true;
        $condition1s = self::getConditions($condition);
        $condition2s = self::getConditions($condition, 'condition2');
        if (!is_null($condition1s) && count($condition1s)>0){
            $is_valid1 = false;
            $standard_data = $dataList['standard_data'];
            foreach ($condition1s as $condition1){
                $enable_result = self::getValueAndCountByName($condition1, 'cyclo_enable');
                if ($enable_result['has_error']) continue;
                $cyclo_enable = $enable_result['value'];
                $count = $enable_result['count'];
                if (!is_numeric($cyclo_enable)) break;
                $amino_count = 0;
                 foreach ($aminoLocations as $amino_location){
                     $single = $amino_location['single'];
                     $single_data = isset($standard_data[$single]) ? $standard_data[$single] : null;
                     if (is_null($single_data)) break;
                     if ($single_data['cyclo_enable']==$cyclo_enable){
                         if ($count==1){
                             $is_valid1 = true;
                         }
                         $amino_count++;
                     }
                 }
                 if ($amino_count>=$count){
                     $is_valid1 = true;
                 }
            }

        }

        if (!is_null($condition2s)){
            $is_valid2 = false;
            foreach ($condition2s as $condition2){
                foreach ($aminoLocations as $aminoLocation){
                   if ($aminoLocation['single']!=$condition2 && $aminoLocation['full']!=$condition2) $is_valid2 = true;
                }
            }
        }

        $is_valid = $is_valid1 && $is_valid2;
        return $is_valid;
    }

    public static function cys2($condition, $dataList){
        $is_valid = false;
        $condition1s = self::getConditions($condition);

        if (!is_null($condition1s)){
            $cys_locations = $dataList['cys_locations'];
            $cys_locations_count = count($cys_locations);
            foreach ($condition1s as $condition1){
                $value_result = self::getValueAndCountByName($condition1, 'cys_2', null);
                if($value_result['has_error']) continue;
                $count = $value_result['count'];
                if ($cys_locations_count/2 >= $count){
                    $is_valid = true;
                }
            }
        }
        return $is_valid;
    }

    public static function nterm($aminoLocations, $condition){
        $is_valid = false;
        $condition1s = self::getConditions($condition);
        $is_valid1 = true;
        if (!is_null($condition1s)){
            $is_valid1 = false;
            foreach ($condition1s as $condition1){
                $amino = self::getValueAndCountByName($condition1, 'nterm')['value'];
                if (strlen($amino)>0 && $aminoLocations[0]['single']==$amino || $aminoLocations[0]['full']==$amino) $is_valid1=true;
            }
        }
        $condition2s = self::getConditions($condition, 'condition2');
        $is_valid2 = true;
        if (!is_null($condition2s)){
            $is_valid2 = false;
            foreach ($condition2s as $condition2){
                $condition2 = trim($condition2);
                if (strpos($condition2, '|')===0){
                    if ($is_valid) break; //条件1和条件2是或的关系
                }

                $amino = self::getValueAndCountByName($condition2, 'nterm')['value'];
                if (strlen($amino)>0 && $aminoLocations[0]['single']!=$amino && $aminoLocations[0]['full']!=$amino) $is_valid2=true;

            }
        }
        $is_valid = $is_valid1 && $is_valid2;
        return $is_valid;
    }

    public static function cterm($aminoLocations, $condition){
        $is_valid = false;
        $condition1s = self::getConditions($condition);
        $is_valid1 = true;
        $cterm_data = $aminoLocations[count($aminoLocations)-1];
        if (!is_null($condition1s)){
            $is_valid1 = false;
            foreach ($condition1s as $condition1){
                $amino = self::getValueAndCountByName($condition1, 'cterm')['value'];
                if (strlen($amino)>0 && $cterm_data['single']==$amino || $cterm_data['full']==$amino) $is_valid1=true;
            }
        }
        $condition2s = self::getConditions($condition, 'condition2');
        $is_valid2 = true;
        if (!is_null($condition2s)){
            $is_valid2 = false;
            foreach ($condition2s as $condition2){
                $condition2 = trim($condition2);
                if (strpos($condition2, '|')===0){
                    if ($is_valid) break; //条件1和条件2是或的关系
                }

                $amino = self::getValueAndCountByName($condition2, 'cterm')['value'];
                if (strlen($amino)>0 && $cterm_data['single']!=$amino && $cterm_data['full']!=$amino) $is_valid2=true;
            }
        }
        $is_valid = $is_valid1 && $is_valid2;
        return $is_valid;
    }

    public static function acid($amino_locations, $condition, $dataList){
        $is_valid = false;
        $acid_count = $dataList['acid_count'];
        $condition1s = self::getConditions($condition);
        if (!is_null($condition1s) && count($condition1s)>0){
            foreach ($condition1s as $condition1){
                $value_result = self::getValueAndCountByName($condition1, 'acid', '');
                if ($acid_count>=$value_result['count']){
                    $is_valid = true;
                    break;
                }
            }
        }
        return $is_valid;
    }

    public static function carrierType($condition, $dataList){
        $is_valid = false;
        $condition1s = self::getConditions($condition);
        $carrierType = $dataList['carrier_type'];
        if (!is_null($condition1s) && count($condition1s)>0){
            foreach ($condition1s as $condition1) {
                $value_result = self::getValueAndCountByName($condition1, 'carrier_type');
                if ($carrierType==$value_result['value']){
                    $is_valid = true;
                }
            }

        }
        return $is_valid;
    }

    public static function synthetic_method($condition, $dataList){
        $is_valid = false;
        $condition1s = self::getConditions($condition);
        $synthetic_method = $dataList['synthetic_method'];
        if (!is_null($condition1s) && count($condition1s)>0){
            foreach ($condition1s as $condition1) {
                $value_result = self::getValueAndCountByName($condition1, 'synthetic_method');
                if ($synthetic_method==$value_result['value']){
                    $is_valid = true;
                }
            }

        }
        return $is_valid;
    }


    private static function getConditions($condition, $conditionName='condition1'){
        $condition = $condition[$conditionName];
        if (strlen($condition)>0){
            $conditions = explode(';', $condition);
            return $conditions;
        }
        return null;
    }

    /**
     * 根据name获取值及出现的个数
     * @param $str string 原字符串
     * @param $name string 操作名称
     * @param string $operator 操作符
     * @param null $operator2 操作符2
     * @return string 结果
     */
    private static function getValueAndCountByName($str, $name, $operator='=',$operator2=null){
        if (is_null($operator2)){
            if (strlen($str)==0) {
                return [
                    'has_error'=>true,
                    'value' => $str,
                    'count' => 1
                ];
            }
            $pos = strpos($str, $name.$operator);
            if ( $pos > -1){
                $value = trim(substr($str, $pos+strlen($name.$operator)));
                if (strpos($value, '[')>-1){
                    $pos1 = strpos($value, '[');
                    $pos2 = strpos($value, ']');
                    $count = substr($value, $pos1+1, $pos2-$pos1-1);
                    $value = substr($value, 0, $pos1);
                    return [
                        'has_error'=>false,
                        'value'=>$value,
                        'count'=>$count
                    ];
                }
                return [
                    'has_error'=>false,
                    'value'=>$value,
                    'count'=>1
                ];
            }
        }
        return [
            'has_error'=>true,
            'value'=>$str,
            'count'=>1
        ];
    }
}